package com.hbnu.cmd.controller;

import com.hbnu.common.factory.ServiceFactory;
import com.hbnu.common.response.ServiceResponse;
import com.hbnu.common.entity.CheckInItem;
import com.hbnu.common.entity.User;
import com.hbnu.common.service.MainService;
import com.hbnu.common.util.CheckUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * 主业务控制台控制器，负责处理用户登录后的核心业务控制台请求。
 * 该控制器与当前登录用户{@link User}绑定，通过{@link ServiceFactory}获取{@link MainService}实例，
 * 处理密码修改、打卡项管理（创建、查询、更新、删除）、每日打卡等业务，
 * 并将处理结果格式化输出到控制台，同时通过SLF4J记录关键操作日志，便于问题追踪。
 */

public class MainController {
    private final Logger logger = LoggerFactory.getLogger(MainController.class);
    private final User loginUser;
    private final MainService mainService;

    /**
     * 构造函数，注入当前登录用户并初始化MainService实例。
     * @param loginUser 当前登录用户实体（含用户名、密码等信息），用于关联所有业务操作
     */
    public MainController(User loginUser) {
        this.loginUser = loginUser;
        this.mainService = ServiceFactory.getMainService(loginUser);
    }

    /**
     * 处理当前登录用户的密码修改请求。
     * 流程：1. 记录请求日志；
     *      2. 通过{@link CheckUtil}校验新密码格式；
     *      3. 校验失败则输出错误并返回；
     *      4. 调用{@link MainService#handleUpdatePassword(String)}处理业务；
     *      5. 根据响应输出结果并记录日志。
     * @param newPassword 用户输入的新密码（需符合格式规范）
     */
    public void handleUpdatePassword(String newPassword, String confirmPassword) {
        logger.info("收到修改密码请求：用户名={}", loginUser.getUsername());

        String errorMessage = CheckUtil.checkPassword(newPassword);
        if (errorMessage != null) {
            System.err.println("修改密码失败：" + errorMessage + "!");
            logger.warn("修改密码失败：用户名={}，原因={}", loginUser.getUsername(), errorMessage);
            return;
        }

        if (!newPassword.equals(confirmPassword)) {
            System.err.println("修改密码失败：两次输入的密码不一致！");
            logger.warn("修改密码失败：用户名={}，原因={}", loginUser.getUsername(), "两次输入的密码不一致");
            return;
        }

        ServiceResponse<Void> response = mainService.handleUpdatePassword(newPassword);
        if (response.isSuccess()) {
            System.out.println(response.getAlertMessage() + "!");
            System.out.println("请重新登录！");
            logger.info("修改密码成功：用户名={}", loginUser.getUsername());
        } else {
            System.err.println("修改密码失败：" + response.getErrorMessage() + "!");
            logger.warn("修改密码失败：用户名={}，原因={}", loginUser.getUsername(), response.getErrorMessage());
        }
    }

    /**
     * 处理当前登录用户创建打卡项的请求。
     * 流程：1. 记录请求日志；
     *      2. 通过{@link CheckUtil}校验打卡项名称格式；
     *      3. 校验失败则输出错误并返回；
     *      4. 调用{@link MainService#handleAddCheckInItem(String)}处理业务；
     *      5. 根据响应输出结果并记录日志。
     * @param itemName 用户输入的打卡项名称
     */
    public void handleAddCheckInItem(String itemName) {
        logger.info("收到创建打卡项请求：用户名={}", loginUser.getUsername());

        String errorMessage = CheckUtil.checkItemName(itemName);
        if (errorMessage != null) {
            System.err.println("创建打卡项失败：" + errorMessage + "!");
            logger.warn("创建打卡项失败：用户名={}，原因={}", loginUser.getUsername(), errorMessage);
            return;
        }

        ServiceResponse<Void> response = mainService.handleAddCheckInItem(itemName);
        if (response.isSuccess()) {
            System.out.println(response.getAlertMessage() + "!");
            logger.info("创建打卡项成功：用户名={}, 打卡项名称={}",
                    loginUser.getUsername(), itemName);
        } else {
            System.err.println("创建打卡项失败：" + response.getErrorMessage() + "!");
            logger.warn("创建打卡项失败：用户名={}，原因={}", loginUser.getUsername(), response.getErrorMessage());
        }
    }

    /**
     * 处理当前登录用户查询所有打卡项的请求。
     * 流程：1. 记录请求日志；
     *      2. 调用{@link MainService#handleGetAllCheckInItems()}查询数据；
     *      3. 查询失败则输出错误并返回；
     *      4. 查询成功则格式化打印打卡项列表（含ID、名称、打卡状态等）。
     */
    public void handleGetAllCheckInItems() {
        logger.info("收到查询打卡项请求：用户名={}", loginUser.getUsername());

        ServiceResponse<List<CheckInItem>> itemsResponse = mainService.handleGetAllCheckInItems();
        if (!itemsResponse.isSuccess()) {
            System.err.println("查询失败：" + itemsResponse.getErrorMessage() + "!");
            return;
        }

        if (itemsResponse.getData().isEmpty()) {
            System.out.print("\n" + " ".repeat(30));
            System.out.println("无记录");
            return;
        }

        for (CheckInItem item : itemsResponse.getData()) {
            System.out.printf(
                    "%-5d%-22s%-11s%-15d%-12d%n",
                    item.getItemId(),
                    item.getItemName(),
                    item.isCheckedInToday() ? "[已打卡]" : "[未打卡]",
                    item.getTotalDays(),
                    item.getContinuousDays()
            );
        }
    }

    /**
     * 处理当前登录用户对指定打卡项的今日打卡请求。
     * 流程：1. 记录请求日志；
     *      2. 通过{@link CheckUtil}校验打卡项ID合法性；
     *      3. 校验失败则输出错误并返回；
     *      4. 调用{@link MainService#handleCheckIn(int)}处理业务；
     *      5. 根据响应输出结果并记录日志。
     * @param itemId 要打卡的打卡项ID（需为正数）
     */
    public void handleCheckIn(int itemId) {
        logger.info("收到打卡请求：用户名={}, 打卡项ID={}", loginUser.getUsername(), itemId);

        String errorMessage = CheckUtil.checkId(itemId);
        if (errorMessage != null) {
            System.err.println("打卡失败：" + errorMessage + "!");
            logger.warn("打卡失败：用户名={}，原因={}", loginUser.getUsername(), errorMessage);
            return;
        }

        ServiceResponse<Void> response = mainService.handleCheckIn(itemId);
        if (response.isSuccess()) {
            System.out.println(response.getAlertMessage() + "!");
            logger.info("打卡成功：用户名={}, 打卡项ID={}", loginUser.getUsername(), itemId);
        } else {
            System.err.println("打卡失败：" + response.getErrorMessage() + "!");
            logger.warn("打卡失败：用户名={}，原因={}", loginUser.getUsername(), response.getErrorMessage());
        }
    }

    /**
     * 处理当前登录用户更新指定打卡项名称的请求。
     * 流程：1. 记录请求日志；
     *      2. 校验打卡项ID合法性和新名称格式；
     *      3. 校验失败则输出错误并返回；
     *      4. 调用{@link MainService#handleUpdateCheckInItem(int, String)}处理业务；
     *      5. 根据响应输出结果并记录日志。
     * @param itemId 要更新的打卡项ID（需为正数）
     * @param newName 打卡项新名称
     */
    public void handleUpdateCheckInItem(int itemId, String newName) {
        logger.info("收到更新打卡项请求：用户名={}, 打卡项ID={}", loginUser.getUsername(), itemId);

        String errorMessage = CheckUtil.checkId(itemId);
        if (errorMessage != null) {
            System.err.println("更新打卡项失败：" + errorMessage + "!");
            logger.warn("更新打卡项失败：用户名={}，原因={}", loginUser.getUsername(), errorMessage);
            return;
        }

        errorMessage = CheckUtil.checkItemName(newName);
        if (errorMessage != null) {
            System.err.println("更新打卡项失败：" + errorMessage + "!");
            logger.warn("更新打卡项失败：用户名={}，原因={}", loginUser.getUsername(), errorMessage);
            return;
        }

        ServiceResponse<Void> response = mainService.handleUpdateCheckInItem(itemId, newName);
        if (response.isSuccess()) {
            System.out.println(response.getAlertMessage() + "!");
            logger.info("更新打卡项成功：用户名={}, 打卡项ID={}", loginUser.getUsername(), itemId);
        } else {
            System.err.println("更新打卡项失败：" + response.getErrorMessage() + "!");
            logger.warn("更新打卡项失败：用户名={}，原因={}", loginUser.getUsername(), response.getErrorMessage());
        }
    }

    /**
     * 处理当前登录用户删除指定打卡项的请求。
     * 流程：1. 记录请求日志；
     *      2. 通过{@link CheckUtil}校验打卡项ID合法性；
     *      3. 校验失败则输出错误并返回；
     *      4. 调用{@link MainService#handleDeleteCheckInItem(int)}处理业务；
     *      5. 根据响应输出结果并记录日志。
     * @param itemId 要删除的打卡项ID（需为正数）
     */
    public void handleDeleteCheckInItem(int itemId) {
        logger.info("收到删除打卡项请求：用户名={}, 打卡项ID={}", loginUser.getUsername(), itemId);

        String errorMessage = CheckUtil.checkId(itemId);
        if (errorMessage != null) {
            System.err.println("删除打卡项失败：" + errorMessage + "!");
            logger.warn("删除打卡项失败：用户名={}，原因={}", loginUser.getUsername(), errorMessage);
            return;
        }

        ServiceResponse<Void> response = mainService.handleDeleteCheckInItem(itemId);
        if (response.isSuccess()) {
            System.out.println(response.getAlertMessage() + "!");
            logger.info("删除打卡项成功：用户名={}, 打卡项ID={}", loginUser.getUsername(), itemId);
        } else {
            System.err.println("删除打卡项失败：" + response.getErrorMessage() + "!");
            logger.warn("删除打卡项失败：用户名={}，原因={}", loginUser.getUsername(), response.getErrorMessage());
        }
    }
}
